//
// Created by xwt
//

#include "ab_process.hpp"
#include "ab_logger.hpp"
#include "ab_common.hpp"
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstdio>
#include <cstring>

namespace anbantech {

    ab_process::ab_process():pid_(-1) {}
    ab_process::~ab_process() = default;

    int ab_process::get_pid() const {
        return pid_;
    }

    int ab_process::start(const char *executable, char *const argv[], char *const envp[]) {
        if(pid_ > 0) {
            LOG(ERROR,"already running %d",pid_);
            return -1;
        }

        pid_t pid;
        if((pid = fork()) < 0) {
            LOG(ERROR,"fork error:%s",strerror(errno));
            return -1;
        }
        if(pid == 0) {
            int ret = execve(executable,argv,envp);
            LOG(ERROR,"ret %d ; execve error:%s", ret, strerror(errno));
        } else {
            pid_ = pid;
        }
        return 0;
    }

    int ab_process::stop(int sig) {
        if(pid_ <= 0) return -1;
        int ret = kill(pid_,sig);
        if(ret != 0){
            LOG(ERROR,"kill(%d,%d) error",pid_,sig);
            return -1;
        }
        pid_ = -1;
        return 0;
    }
    //return -1 if child process exit error
    int ab_process::wait(int opt) {
        int status;
        bool crashed = false;
        /* Parent process */
        waitpid(pid_, &status, opt);
        if (WIFEXITED(status)) {
            LogLevel level;
            if(WEXITSTATUS(status) == 0) {
                level = INFO;
            }else {
                level = WARN;
                crashed = true;
            }
            LOG(level, "Child exited with status %d", WEXITSTATUS(status));
        } else if (WIFSIGNALED(status)) {
            crashed = true;
            LOG(ERROR, "Child was terminated by signal %d", WTERMSIG(status));
        } else if (WIFSTOPPED(status)) {
            //don't care
            LOG(ERROR, "Child was stopped by signal %d", WSTOPSIG(status));
        } else if (WIFCONTINUED(status)) {
            //don't care
            LOG(ERROR, "Child continued");
        }
        pid_ = -1;
        if(crashed){
            return -1;
        }
        return 0;
    }

} // anbantech